package com.feishi.core.util.common.lecode.thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: caixq
 * Date: 2020-08-19
 * Time: 上午10:37
 */
public class H2O {
    public static void main(String[] args) throws InterruptedException {

        H2O h2O=new H2O();
        int n=1;
        new Thread(()->{
            for (int j = 0; j < n; j++) {
                try {
                    h2O.oxygen(()-> System.out.print('O'));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            System.out.println("o end");
        }).start();
        new Thread(()->{
            for (int j = 0; j < n*2; j++) {
                try {
                    h2O.hydrogen(()-> System.out.print('H'));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("h end");
        }).start();
    }

    public H2O() {

    }
    private Barrier barrier=new Barrier();
    static class Barrier{
        int h=0;
        int o=0;

        public boolean full() {
            return h==2&&o==1;
        }
        public void clear() {
            h=0;
            o=0;
        }
    }

    public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {


        // releaseHydrogen.run() outputs "H". Do not change or remove this line.
        synchronized (barrier){
            while (true){
                if(barrier.h<2){
                    barrier.h++;
                    releaseHydrogen.run();
                    if(barrier.full()){
                        barrier.clear();
                        barrier.notifyAll();
                    }
                    break;
                }else {
                    barrier.wait();
                }
            }

        }
    }

    public void oxygen(Runnable releaseOxygen) throws InterruptedException {
        // releaseOxygen.run() outputs "O". Do not change or remove this line.

        synchronized (barrier){
            while (true){
                if(barrier.o<1){
                    barrier.o++;
                    releaseOxygen.run();
                    if(barrier.full()){
                        barrier.clear();
                        barrier.notifyAll();
                    }
                    break;
                }else {
                    barrier.wait();
                }
            }
        }
    }
}